package com.nulldev.util.web.YouTubeExtractor.signatures.extractors;

import javax.script.ScriptEngine;
import javax.script.ScriptException;

import com.nulldev.util.JVM.JVM;
import com.nulldev.util.concurrency.threadIt.v4.emapi.ExecutorManager;
import com.nulldev.util.concurrency.threadIt.v4.emapi.uft.Executable;
import com.nulldev.util.scripting.ScriptAPI.nScripting;
import com.nulldev.util.web.YouTubeExtractor.signatures.ExtractedSignatureData;
import com.nulldev.util.web.YouTubeExtractor.signatures.extractor.Extractor;

public class NashornBasedExtractor extends Extractor {
	private final ScriptEngine ns;

	public NashornBasedExtractor(final ExtractedSignatureData data) {
		super(data);
		if (!nScripting.isNashornInstalled()) {
			throw new RuntimeException("Extractors.Nashorn --> Nashorn isn't detected on your JRE.");
		}
		this.ns = nScripting.cached().getEngineByName("nashorn");
		if (this.ns != null) {
			try {
				this.ns.eval(this.getCode());
			} catch (ScriptException e) {
				JVM.errorln(e);
			}
		}
	}

	@Override
	public String decrypt(final String signature) {
		if (signature == null)
			return null;
		try {
			return (String) this.ns.eval(this.getFunctionName() + "(\"" + signature + "\");");
		} catch (ScriptException e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public Executable<String> decryptTask(final String signature) {
		return ExecutorManager.make(() -> {
			return decrypt(signature);
		});
	}

	@Override
	public String getCode() {
		return this.getExtractedData().getCode();
	}

	@Override
	public String getFunctionCode() {
		return this.getExtractedData().getFunctionCode();
	}

	@Override
	public String getFunctionName() {
		return this.getExtractedData().getFunctionName();
	}

	@Override
	public Extractor updateESD(final ExtractedSignatureData newData) {
		super.setExtractedData(newData);
		if (this.ns != null) {
			try {
				this.ns.eval("delete " + this.getFunctionName());
				this.ns.eval(this.getCode());
			} catch (ScriptException e) {
				JVM.errorln(e);
			}
		}
		return this;
	}
}
